/*
 * Copyright (C) 2021 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.github.ppamorim.cult.customview;

import ohos.agp.colors.RgbColor;
import ohos.agp.components.AttrHelper;
import ohos.agp.components.AttrSet;
import ohos.agp.components.Component;
import ohos.agp.components.StackLayout;
import ohos.agp.components.element.ShapeElement;
import ohos.agp.render.BlurDrawLooper;
import ohos.agp.render.Canvas;
import ohos.agp.render.Paint;
import ohos.agp.render.Path;
import ohos.agp.utils.Color;
import ohos.agp.utils.RectFloat;
import ohos.app.Context;
import ohos.hiviewdfx.HiLog;
import ohos.hiviewdfx.HiLogLabel;

/**
 * 基础可设置阴影效果的Layout
 *
 * @author xuexiang
 * @since 2019/1/14 下午10:00
 */
public class BaseShadowLayout extends StackLayout implements Component.DrawTask, Component.EstimateSizeListener {
    /**
     * 波纹形状 圆形
     */
    public static final int SHAPE_TYPE_ROUND = 0;
    /**
     * 波纹形状 方形
     */
    public static final int SHAPE_TYPE_RECTANGLE = 1;
    /**
     * 圆角设置 没有圆角
     */
    public static final int NO_CORNERS = 100001;
    /**
     * 圆角设置 圆角在上面
     */
    public static final int TOP_CORNERS = 100002;
    /**
     * 圆角设置 圆角在下面
     */
    public static final int BOTTOM_CORNERS = 100003;
    /**
     * 阴影设置 没有阴影
     */
    private static final int NO_SHADOW = 0;
    private static final int TWO = 2;
    private static final float F_TWO = 2f;
    private static final float FIVE = 5f;
    private static final int THIRTY = 30;
    private static final float STORKE_LINE = 0.8f;
    private static final HiLogLabel TAG = new HiLogLabel(3, 0xD001100, "ZyTest");

    protected int mWidth;
    protected int mHeight;
    protected Paint mBackgroundPaint;
    protected Paint mStrokePaint;
    protected Paint mShadowPaint;
    protected int mShapeType;
    /**
     * 圆角大小
     */
    protected int mRadius;
    /**
     * 背景颜色
     */
    protected Color unpressedColor;
    /**
     * 圆角位置 0 表示没有  TOP_CORNERS 表示上圆角  BOTTOM_CORNERS 表示下圆角
     */
    protected int cornersLocation;
    /**
     * 阴影大小 0 表示没有  1 表示5vp的阴影  2 表示10vp的阴影
     */
    protected int mShadowElevation;

    protected RectFloat mRectF;

    /**
     * 构造函数
     *
     * @param context 上下文
     */
    public BaseShadowLayout(Context context) {
        super(context);
        init(context, null);
    }

    /**
     * 构造函数
     *
     * @param context 上下文
     * @param attrSet 属性
     */
    public BaseShadowLayout(Context context, AttrSet attrSet) {
        super(context, attrSet);
        init(context, attrSet);
    }

    /**
     * 构造函数
     *
     * @param context 上下文
     * @param attrSet 属性
     * @param styleName 样式
     */
    public BaseShadowLayout(Context context, AttrSet attrSet, String styleName) {
        super(context, attrSet, styleName);
        init(context, attrSet);
    }

    /**
     * 初始化
     *
     * @param context 上下文
     * @param attrSet 属性
     */
    protected void init(final Context context, final AttrSet attrSet) {
        mShapeType = AttrValue.get(attrSet, "sb_shape_type", SHAPE_TYPE_RECTANGLE);
        mRadius = AttrValue.getDimension(attrSet, "sb_radius", AttrHelper.vp2px(TWO, context));
        unpressedColor = AttrValue.get(attrSet, "sb_color_unpressed", Color.TRANSPARENT);
        cornersLocation = AttrValue.get(attrSet, "sb_corners_location", NO_CORNERS);
        mShadowElevation = AttrValue.get(attrSet, "sb_shadow_elevation", NO_SHADOW);

        mBackgroundPaint = new Paint();
        mBackgroundPaint.setStyle(Paint.Style.FILL_STYLE);
        mBackgroundPaint.setAlpha(Color.alpha(unpressedColor.getValue()));
        mBackgroundPaint.setColor(unpressedColor);
        mBackgroundPaint.setAntiAlias(true);

        mStrokePaint = new Paint();
        mStrokePaint.setStyle(Paint.Style.STROKE_STYLE);
        mStrokePaint.setColor(new Color(Color.getIntColor("#E6E6E6")));
        mStrokePaint.setStrokeWidth(AttrHelper.vp2px(STORKE_LINE, context));
        mStrokePaint.setAntiAlias(true);

        mShadowPaint = new Paint();
        mShadowPaint.setColor(Color.WHITE);
        mShadowPaint.setAntiAlias(true);
        mShadowPaint.setBlurDrawLooper(new BlurDrawLooper(mRadius,
            FIVE, FIVE * mShadowElevation,
            new Color(Color.getIntColor("#F2F2F2"))));

        this.setClickable(true);
        this.eraseOriginalBackgroundColor(unpressedColor);
        addDrawTask(this, DrawTask.BETWEEN_BACKGROUND_AND_CONTENT);
        setEstimateSizeListener(this);
    }

    @Override
    public boolean onEstimateSize(int i, int i1) {
        mWidth = EstimateSpec.getSize(i);
        mHeight = EstimateSpec.getSize(i1);
        if (mShadowElevation == 0) {
            mRectF = new RectFloat(0 + AttrHelper.vp2px(F_TWO, getContext()), 0,
                mWidth - AttrHelper.vp2px(F_TWO, getContext()), mHeight);
        } else {
            mRectF = new RectFloat(0 + AttrHelper.vp2px(F_TWO, getContext()), 0,
                mWidth - AttrHelper.vp2px(F_TWO, getContext()),
                mHeight - AttrHelper.vp2px(FIVE, getContext()));
        }
        return false;
    }

    @Override
    public void onDraw(Component component, Canvas canvas) {
        if (mBackgroundPaint == null) {
            return;
        }
        if (mShapeType == SHAPE_TYPE_ROUND) {
            canvas.drawCircle(mWidth / F_TWO, mHeight / F_TWO, mWidth / F_TWO, mBackgroundPaint);
        } else {
            Path path = new Path();
            if (cornersLocation == NO_CORNERS) {
                path.addRoundRect(mRectF, new float[]{0, 0, 0, 0, 0, 0, 0, 0}, Path.Direction.CLOCK_WISE);
            } else if (cornersLocation == TOP_CORNERS) {
                path.addRoundRect(mRectF, new float[]{THIRTY, THIRTY, THIRTY, THIRTY, 0, 0, 0, 0},
                    Path.Direction.CLOCK_WISE);
            } else if (cornersLocation == BOTTOM_CORNERS) {
                path.addRoundRect(mRectF, new float[]{0, 0, 0, 0, THIRTY, THIRTY, THIRTY, THIRTY},
                    Path.Direction.CLOCK_WISE);
            }
            if (mShadowElevation != 0) {
                canvas.drawPath(path, mShadowPaint);
            }
            canvas.drawPath(path, mBackgroundPaint);
            canvas.drawPath(path, mStrokePaint);
        }
    }

    /**
     * 设置背景透明
     *
     * @param color 颜色
     */
    protected void eraseOriginalBackgroundColor(Color color) {
        if (color != Color.TRANSPARENT) {
            ShapeElement shapeElement = new ShapeElement();
            shapeElement.setRgbColor(RgbColor.fromArgbInt(Color.TRANSPARENT.getValue()));
            this.setBackground(shapeElement);
        }
    }

    public int getCornersLocation() {
        return cornersLocation;
    }

    /**
     * Set the unpressed color.
     *
     * @param color the color of the background
     */
    public void setUnpressedColor(Color color) {
        mBackgroundPaint.setAlpha(Color.alpha(color.getValue()));
        mBackgroundPaint.setColor(color);
        eraseOriginalBackgroundColor(color);
        invalidate();
    }

    public int getShapeType() {
        return mShapeType;
    }

    /**
     * Set the shape type.
     *
     * @param shapeType SHAPE_TYPE_ROUND or SHAPE_TYPE_RECTANGLE
     */
    public void setShapeType(int shapeType) {
        mShapeType = shapeType;
        invalidate();
    }

    public int getRadius() {
        return mRadius;
    }

    /**
     * Set the radius if the shape type is SHAPE_TYPE_ROUND.
     *
     * @param radius by px.
     */
    public void setRadius(int radius) {
        mRadius = radius;
        invalidate();
    }

    /**
     * 设置圆角弧度
     *
     * @param radius 圆角弧度
     */
    public void setRadius(float radius) {
        setRadius((int) radius);
    }

    /**
     * 设置背景颜色
     *
     * @param colorRes 资源颜色
     */
    public void setColorRes(int colorRes) {
        unpressedColor = new Color(getContext().getColor(colorRes));
        mBackgroundPaint.setColor(unpressedColor);
        invalidate();
    }

    /**
     * 设置背景颜色
     *
     * @param color 颜色值
     */
    public void setColor(int color) {
        unpressedColor = new Color(color);
        mBackgroundPaint.setColor(unpressedColor);
        invalidate();
    }

    /**
     * 设置阴影大小
     *
     * @param value 阴影值
     */
    public void setElevation(float value) {
        if (value > FIVE) {
            mShadowElevation = TWO;
        } else {
            mShadowElevation = 1;
        }
    }

    /**
     * 是否有阴影
     *
     * @return true 有 false 没有
     */
    public boolean hasElevation() {
        return mShadowElevation != 0 ? true : false;
    }

    /**
     * 设置左阴影
     *
     * @param show true设置 false 不设置
     */
    public void showLeftEdgeShadow(boolean show) {
        HiLog.info(TAG, "showLeftEdgeShadow() only work for pre API 21.");
    }

    /**
     * 设置上阴影
     *
     * @param show true设置 false 不设置
     */
    public void showTopEdgeShadow(boolean show) {
        HiLog.info(TAG, "showTopEdgeShadow() only work for pre API 21.");
    }

    /**
     * 设置又阴影
     *
     * @param show true设置 false 不设置
     */
    public void showRightEdgeShadow(boolean show) {
        HiLog.info(TAG, "showRightEdgeShadow() only work for pre API 21.");
    }

    /**
     * 设置下阴影
     *
     * @param show true设置 false 不设置
     */
    public void showBottomEdgeShadow(boolean show) {
        HiLog.info(TAG, "showBottomEdgeShadow() only work for pre API 21.");
    }
}
